package com.atguigu.tingshu.order.strategy.impl;

import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.google.common.collect.Lists;

import java.math.BigDecimal;

import com.atguigu.tingshu.account.client.UserAccountFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.order.service.OrderDerateService;
import com.atguigu.tingshu.order.service.OrderDetailService;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.order.strategy.SaveOrderStrategy;
import com.atguigu.tingshu.vo.account.AccountLockResultVo;
import com.atguigu.tingshu.vo.account.AccountLockVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Author  王东剑
 * Created on 23/6/2024 PM1:59
 * Package_name com.atguigu.tingshu.order.strategy.impl
 * Description
 */
@Service
@Slf4j
public class AccountSaveOrderStrategy implements SaveOrderStrategy {
	@Autowired
	private OrderInfoService orderInfoService;
	@Autowired
	private OrderDetailService orderDetailService;
	@Autowired
	private OrderDerateService orderDerateService;
	@Autowired
	private RedissonClient redissonClient;
	@Autowired
	private UserAccountFeignClient userAccountFeignClient;
	@Autowired
	private KafkaService kafkaService;

	@Override
	public OrderInfoVo saveOrder(OrderInfoVo orderInfoVo) {
		System.out.println("AccountSaveOrderStrategy.saveOrder");
		// 1.金额检查与锁定
		Long userId = AuthContextHolder.getUserId();
		String orderNo = orderInfoVo.getTradeNo();
		BigDecimal orderAmount = orderInfoVo.getOrderAmount();
		List<OrderDetailVo> orderDetailVoList = orderInfoVo.getOrderDetailVoList();
		String itemName = orderDetailVoList.get(0).getItemName();
		AccountLockVo accountLockVo = new AccountLockVo();
		accountLockVo.setOrderNo(orderNo);
		accountLockVo.setUserId(userId);
		accountLockVo.setAmount(orderAmount);
		accountLockVo.setContent(itemName);
		Result<AccountLockResultVo> resultVoResult = userAccountFeignClient.checkAndLock(accountLockVo);
		Integer code = resultVoResult.getCode();
		// 调用失败
		if (!ResultCodeEnum.SUCCESS.getCode().equals(code)) {
			throw new GuiguException(resultVoResult.getCode(), resultVoResult.getMessage());
		}
		// 检查并锁定可用余额
		try {
			// 2.保存订单信息,明细,减免到数据库
			this.saveOrderInfoAndOrderDetailAndOrderDerate(orderInfoVo,
					orderInfoService,
					orderDetailService,
					orderDerateService);
		} catch (Exception e) {
			e.printStackTrace();
			//  异常手动解锁账户
			kafkaService.sendMsg(KafkaConstant.QUEUE_ACCOUNT_UNLOCK, orderNo);
			// 抛出异常
			throw new GuiguException(ResultCodeEnum.DATA_ERROR);
		}
		return orderInfoVo;
	}

	/**
	 * 添加未支付的订单进入延迟队列
	 *
	 * @param orderNo
	 */
	public void addDelayQueue(String orderNo) {
		RBlockingDeque<String> rBlockingDeque = redissonClient.getBlockingDeque(RedisConstant.QUEUE_ORDER_CANCEL);
		RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(rBlockingDeque);
		// TODO: 延时时间记得改回 RedisConstant.DELAY_TIME
		delayedQueue.offer(orderNo, 20, TimeUnit.SECONDS);
		log.info("添加延时队列成功 ，延迟时间：{}，订单id：{}", RedisConstant.DELAY_TIME, orderNo);
	}

	@Override
	public String getPayWay() {
		return SystemConstant.ORDER_PAY_ACCOUNT;
	}

	@Override
	public void saveOrderAfterProcess(String orderNo) {
		// 3.修改订单状态,
		orderInfoService.orderPaySuccess(orderNo);
		// 4.扣减账户金额  1.无异常(tingshu.account.minus) 2.有异常(AccountLockResultVo) (tingshu.account.unlock)
		kafkaService.sendMsg(KafkaConstant.QUEUE_ACCOUNT_MINUS, orderNo);
		// 添加未支付的订单进入延迟队列
		this.addDelayQueue(orderNo);
	}
}
